#region Using

using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.IO;
using System.Collections.Generic;
using BlogEngine.Core;

#endregion

namespace Controls
{
    /// <summary>
    /// Builds a category list.
    /// </summary>
    public class CategoryMenu : Control
    {
        static CategoryMenu()
        {
            Post.Saved += delegate { _Html = null; };
            Category.Saved += delegate { _Html = null; };
        }

        #region Properties

        private bool _ShowRssIcon = true;
        /// <summary>
        /// Gets or sets whether or not to show feed icons next to the category links.
        /// </summary>
        public bool ShowRssIcon
        {
            get { return _ShowRssIcon; }
            set { _ShowRssIcon = value; }
        }

        private static object _SyncRoot = new object();
        private static string _Html;
        private string Html
        {
            get
            {
                if (_Html == null)
                {
                    lock (_SyncRoot)
                    {
                        if (_Html == null)
                        {
                            HtmlGenericControl ul = BindCategories();
                            System.IO.StringWriter sw = new System.IO.StringWriter();
                            ul.RenderControl(new HtmlTextWriter(sw));
                            _Html = sw.ToString();
                        }
                    }
                }

                return _Html;
            }
        }

        #endregion

        private HtmlGenericControl BindCategories()
        {
            //create the container
            HtmlGenericControl div = new HtmlGenericControl("div");
            div.ID = "categorymenu";

            //recursively get all children
            CreateMenuItems(div, Guid.Empty);

            return div;
        }

        private int CreateMenuItems(HtmlGenericControl container, Guid parentId)
        {
            //no children so return
            if (!HasChildren(parentId))
            {
                return 0;
            }

            int theCount = 0;
            HtmlGenericControl ul = new HtmlGenericControl("ul");

            foreach (Category cat in Category.GetChildCategories(parentId))
            {

                HtmlGenericControl li = new HtmlGenericControl("li");

                int myCount = CreateMenuItems(li, cat.Id) + Post.GetByCategory(cat).Count;
                theCount += myCount;

                //no subcategories had items to display and we don't so skip to the next one.
                if (myCount == 0)
                {
                    continue;
                }
                
                //this seems backwards but we have to inject these into the li control after
                //possibly adding other sub-categories...
                LiteralControl counttext = new LiteralControl(" (" + myCount + ")");
                li.Controls.AddAt(0,counttext);

                HtmlAnchor anc = new HtmlAnchor();
                anc.HRef = Utils.RelativeWebRoot + "category/" + cat.Slug + BlogSettings.Instance.FileExtension;
                anc.InnerHtml = HttpUtility.HtmlEncode(cat.Title);
                anc.Title = "Category: " + cat.Title;

                li.Controls.AddAt(0, anc);

                if (ShowRssIcon)
                {
                    HtmlImage img = new HtmlImage();
                    img.Src = Utils.RelativeWebRoot + "pics/rssButton.gif";
                    img.Alt = "RSS feed for " + cat.Title;
                    img.Attributes["class"] = "rssButton";

                    HtmlAnchor feedAnchor = new HtmlAnchor();
                    feedAnchor.HRef = Utils.RelativeWebRoot + "syndication.axd?category=" + cat.Id.ToString();
                    feedAnchor.Attributes["rel"] = "nofollow";
                    feedAnchor.Controls.Add(img);

                    li.Controls.AddAt(0,feedAnchor);
                }

                //finally add this item to the list
                ul.Controls.Add(li);
            }

            //only add the list if we contributed something
            if (theCount > 0)
            {
                container.Controls.Add(ul);
            }

            return theCount;
        }

        private bool HasChildren(Guid categoryId)
        {
            bool returnValue = false;

            foreach (Category cat in Category.Items)
            {
                if (cat.Parent == categoryId)
                {
                    returnValue = true;
                    break;
                }
            }

            return returnValue;
        }

        /// <summary>
        /// Renders the control.
        /// </summary>
        public override void RenderControl(HtmlTextWriter writer)
        {
            writer.WriteLine(Html);
        }
    }
}